装饰者模式 Decorator Pattern
设计原则 五:
开放-关闭原则,类应该对拓展开放,对修改关闭。
定义装饰者模式
装饰者模式:动态地将责任附加到对象上。若要扩展功能,装饰者提供了比继承更有弹性的替代方案。
Java 装饰者者模式的应用,Java I/O 流的
装饰者和被装饰对象有相同的超类型。
你可以用一个或多个装饰者包装一个对象。
既然装饰者和被装饰对象有相同的超类型,所以在任何需要原始对象(被包装的)的场合, 可以用装饰过的对象代替它。
装饰者可以在所委托被装饰者的行为之前与/或之后,加上自己的行为,以达到特定的目的。(重要)
对象可以在任何时候被装饰,所以可以在运行时动态地、不限量地用你喜欢的装饰者来装饰 对象。
类图
例图
装饰者类解析
1 2 3 4 5 6 7 8 9 10 11
| package headfirst.decorator.starbuzz;
public abstract class Beverage { String description = "Unknown Beverage"; public String getDescription() { return description; } public abstract double cost(); }
|
1 2 3 4 5
| package headfirst.decorator.starbuzz;
public abstract class CondimentDecorator extends Beverage { public abstract String getDescription(); }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48
| package headfirst.decorator.starbuzz;
public class DarkRoast extends Beverage { public DarkRoast() { description = "Dark Roast Coffee"; } public double cost() { return .99; } }
package headfirst.decorator.starbuzz;
public class Decaf extends Beverage { public Decaf() { description = "Decaf Coffee"; } public double cost() { return 1.05; } }
package headfirst.decorator.starbuzz;
public class Espresso extends Beverage { public Espresso() { description = "Espresso"; } public double cost() { return 1.99; } }
package headfirst.decorator.starbuzz;
public class HouseBlend extends Beverage { public HouseBlend() { description = "House Blend Coffee"; } public double cost() { return .89; } }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71
| package headfirst.decorator.starbuzz;
public class Milk extends CondimentDecorator { Beverage beverage;
public Milk(Beverage beverage) { this.beverage = beverage; }
public String getDescription() { return beverage.getDescription() + ", Milk"; }
public double cost() { return .10 + beverage.cost(); } }
package headfirst.decorator.starbuzz;
public class Mocha extends CondimentDecorator { Beverage beverage; public Mocha(Beverage beverage) { this.beverage = beverage; } public String getDescription() { return beverage.getDescription() + ", Mocha"; } public double cost() { return .20 + beverage.cost(); } }
package headfirst.decorator.starbuzz;
public class Soy extends CondimentDecorator { Beverage beverage;
public Soy(Beverage beverage) { this.beverage = beverage; }
public String getDescription() { return beverage.getDescription() + ", Soy"; }
public double cost() { return .15 + beverage.cost(); } }
package headfirst.decorator.starbuzz; public class Whip extends CondimentDecorator { Beverage beverage; public Whip(Beverage beverage) { this.beverage = beverage; } public String getDescription() { return beverage.getDescription() + ", Whip"; } public double cost() { return .10 + beverage.cost(); } }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| package headfirst.decorator.starbuzz;
public class StarbuzzCoffee { public static void main(String args[]) { Beverage beverage = new Espresso(); System.out.println(beverage.getDescription() + " $" + beverage.cost()); Beverage beverage2 = new DarkRoast(); beverage2 = new Mocha(beverage2); beverage2 = new Mocha(beverage2); beverage2 = new Whip(beverage2); System.out.println(beverage2.getDescription() + " $" + beverage2.cost()); Beverage beverage3 = new HouseBlend(); beverage3 = new Soy(beverage3); beverage3 = new Mocha(beverage3); beverage3 = new Whip(beverage3); System.out.println(beverage3.getDescription() + " $" + beverage3.cost()); } }
|